package com.dk.hi.core.helper;

import java.util.ArrayList;
import java.util.List;

import org.newdawn.slick.SlickException;
import org.newdawn.slick.UnicodeFont;

import com.drakulo.hi.gfx.FontFactory;

public class TextHelper {
	private static String chars4 = "fijrt!:,.";
	private static String chars5 = " ";
	private static String chars6 = "*";
	private static String chars8 = "abcdeghknopqsuvxyz?FLT";
	private static String chars10 = "ABCDEHKNRSUVXYZ";
	private static String chars11 = "w";
	private static String chars12 = "GMQ";
	private static String chars13 = "mw";
	private static String chars14 = "W";

	/**
	 * Utility method to draw a text on screen using the default font
	 * 
	 * @param x
	 *            - X coordinates
	 * @param y
	 *            - Y coordinates
	 * @param c
	 *            - the character to draw
	 * @throws SlickException
	 */
	public static void drawString(int x, int y, char c) throws SlickException {
		drawString(x, y, String.valueOf(c));
	}

	/**
	 * Utility method to draw a text on screen using the default font
	 * 
	 * @param x
	 *            - X coordinates
	 * @param y
	 *            - Y coordinates
	 * @param text
	 *            - the text to draw
	 * @throws SlickException
	 */
	public static void drawString(int x, int y, String text) throws SlickException {
		UnicodeFont font = FontFactory.getDefaultFont();
		font.drawString(x, y, text);
	}

	/**
	 * Draws a text in a given space. Automatically wrap lines
	 * 
	 * @param x
	 *            - X coordinates
	 * @param y
	 *            - Y coordinates
	 * @param lineWidth
	 *            - the line width
	 * @param text
	 *            - the text to draw
	 * @throws SlickException
	 */
	public static void drawText(int x, int y, int lineWidth, String text) throws SlickException {
		List<String> lines = splitTextIntoLines(text, lineWidth);
		int lineNumber = 0;
		for (String line : lines) {
			drawString(x, y + 15 * lineNumber, " " + line);
			lineNumber++;
		}
	}

	/**
	 * @param s
	 *            - the char
	 * @return the screen width of a char
	 */
	private static Integer getCharSize(String s) {
		if (chars4.contains(s)) {
			return 4;
		} else if (chars5.contains(s)) {
			return 5;
		} else if (chars6.contains(s)) {
			return 6;
		} else if (chars8.contains(s)) {
			return 8;
		} else if (chars10.contains(s)) {
			return 10;
		} else if (chars11.contains(s)) {
			return 11;
		} else if (chars12.contains(s)) {
			return 12;
		} else if (chars13.contains(s)) {
			return 13;
		} else if (chars14.contains(s)) {
			return 14;
		} else {
			return 10;
		}
	}

	/**
	 * Calculate the screen length of a text
	 * 
	 * @param text
	 *            - the text to test
	 * @return the screen length of the text
	 */
	private static Integer getScreenLengthOf(String text) {
		int total = 0;
		for (int i = 0; i < text.length(); i++) {
			total += getCharSize(String.valueOf(text.charAt(i)));
		}
		return total;
	}

	/**
	 * Splits a text into lines with the specified line width
	 * 
	 * @param text
	 *            - the text to split
	 * @param lineWidth
	 *            - the line width
	 * @return
	 */
	public static List<String> splitTextIntoLines(String text, int lineWidth) {
		String[] words = text.split(" ");
		List<String> lines = new ArrayList<String>();
		StringBuilder lineBuffer = new StringBuilder(lineWidth);
		String currentWord = null;
		int currentLineLength = 0;
		int currentWordLength = 0;
		for (int wordCount = 0; wordCount < words.length; wordCount++) {
			currentWord = words[wordCount];
			currentLineLength = getScreenLengthOf(lineBuffer.toString());
			currentWordLength = getScreenLengthOf(currentWord);
			if (currentLineLength + 1 + currentWordLength > lineWidth) {
				// Drawing the current word would go out of the drawing zone.
				// The line is added to the result and we start a new line
				// buffer
				lines.add(lineBuffer.toString());
				lineBuffer.setLength(0);
				lineBuffer.append(currentWord);
			} else {
				// We can add the current word at the end of the line
				lineBuffer.append(" ").append(currentWord);
			}
		}
		lines.add(lineBuffer.toString());
		return lines;
	}
}
